package net.scala.chapter3.c

/**
 * 在Scala中case class一般用于做DTO(Data Transfer object)。比起传统的JavaBean实体对象，
 * case class中会被Scala编译器自动添加上访问器、伴生对象(companion object)。
 * 1. 参数默认是使用val关键字修饰，如果有必要，可以使用var关键字以实现修改器，但是一般不推荐这样做。
 * 2. 自Scala2.8自后，case class中参数列表可以为空，但是不赞成(deprecated)，推荐加上()。
 * 3. abstract case class的伴生对象(companion object)不能实例化，但通过case object实现，但是它是单例的、序列化的。
 * @author Barudisshu
 */
case class Person1(firstName: String, lastName: String)
case class Person2
// 不推荐的做法，应该写成case class Person()

// 抽象的case class不会在伴生对象中生成apply方法，因为抽象类不能实例化。
abstract case class Person3(firstName: String, lastName: String)

case object Person4{
  def apply(firstName:String,lastName:String) = new Person3(firstName,lastName) {}
}

object Case_Class_Usage {
  def main(args: Array[String]) {

    // 伴生对象是自动生成的
    val p1 = Person1("Chemnk", "Barudisshu")
    println(p1.firstName)
    println(p1.lastName)

    val p2 = new Person1("Chemnk", "Barudisshu")
    println(p1 equals p2)

    // 两者具有相同的序列号
    println(p1.hashCode)
    println(p2.hashCode)

    println(p1.toString)

    // 这里将发生编译错误，因为abstract case class Person3的伴生对象不包含apply方法，
    // 因此不能接收参数，请使用new Person3声明并实例化
//    val p3 = Person3("Chemnk", "Barudisshu")
    val p3 = new Person3("Chemnk","Barudisshu"){}
    println(p3.firstName)
    println(p3.lastName)

    // 用于正则匹配
    p1 match {
      case Person1(first,last) => println(">>>> " + first + ", " + last)
    }

    // 在for-comprehension中使用模式匹配

    val people = List(Person1("Simon","Kish"),Person1("Phil","Marzullo"),Person1("Eric","Weimer"))
    for(Person1(first,last) <- people) println(first + "," + last)
  }
}



